/* 
 * File:   main.cpp
 * Author: afonso
 *
 * Created on December 2, 2013, 10:30 PM
 */

#include <cstdlib>
#include <iostream>
#include <openssl/rand.h>
#include <openssl/err.h>

using namespace std;

/*
 * Implementação de um One-time Pad.
 */
int main(int argc, char** argv) {
    int r = FIPS_mode_set(1);
    if(r == 0){
        cout << "Não consegui entrar no modo FIPS." << endl;
    } else{
        cout << "* OpenSSL no modo FIPS." << endl;
    }
    
    
    //Verifica o FIPS
    if (FIPS_mode() == 0){
        cout << "* O modo FIPS não está ativado." << endl;
        cout << "* Utilizando RAND_SSLeay como PRNG." << endl;
    } else {
        cout << "* O modo FIPS (140-2) está ativado." << endl;
        cout << "* Utilizando 256-bit CTR AES como PRNG." << endl;
    }
    
    //Caso se deseja inicializar o gerador com mais entropia.
    /*
    int rc = RAND_load_file("/dev/random", 32);
    if (rc != 32) {
        cout << "Falha mínima." << endl;
        return 0;
    }
    cout << "Gerador carregado." << endl;
    */

    //Texto aberto
    char plaintext[11] = "OpenSSL!!!";
    //Cifra
    char cifra[11];
    //Chave do OTP.
    unsigned char chave[11];
    //Sorteia a chave usando o OpenSSL
    RAND_bytes(chave, sizeof (chave));
    
    //Imprime o texto aberto
    cout << "Texto aberto: " << plaintext << endl;

    cout << "Cifra: ";
    //Realiza a cifragem
    for (int x = 0; x < 10; x++) {
        //Realiza o XOR entre um byte
        //de texto aberto e um byte aleatório.
        plaintext[x] = plaintext[x] ^ chave[x];
        //Imprime a cifra byte a byte.
        cout << plaintext[x];
        //Guarda a cifra.
        cifra[x] = plaintext[x];
    }
    cout << endl;

    //Realiza a decifragem
    cout << "Texto decifrado: ";
    for (int x = 0; x < 10; x++) {
        //Realiza o XOR entre um byte de texto aberto
        //e um byte aleatório.
        cifra[x] = cifra[x] ^ chave[x];
        //Imprime a cifra byte a byte.
        cout << cifra[x];
    }

    cout << endl;
    
    cout << "Número aleatório com OpenSSL:" << endl;
    int numero;
    //Sorteia o número usando o OpenSSL
    RAND_bytes(chave, sizeof (numero));
    printf("%d\n", numero);

    return 0;
}